﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using WcfCore;

namespace WcfClientHost
{
	public class PerformanceCounterLogInfo
	{
		public string Name;
		public int LogIntervalInSeconds;
		public string MachineName;
		public string PerformanceCounterFilename;
		public string OutputFilename;
		public string LogManExePath;
		public string PsExecExePath;
		public string Username;
		public string Password;
	}

	public class PerformanceCounterLog : IDisposable
	{
		public PerformanceCounterLog(PerformanceCounterLogInfo[] infos)
		{
			_infos = infos;
			PsExecExePath = infos[0].PsExecExePath;
			LogManExePath = infos[0].LogManExePath;

			// Clean up any mess from before
			StopPerformanceCounterLogs();
			DeletePerformanceCounterCollections();

			CreatePerformanceCounterCollections();
			StartPerformanceCounterLogs();
		}

		private readonly PerformanceCounterLogInfo[] _infos;
		public PerformanceCounterLogInfo[] Infos
		{
			get
			{
				return _infos;
			}
		}

		private string LogManExePath;
		private string PsExecExePath;

		#region IDisposable Members
		private bool _disposed;
		private void Dispose(bool disposing)
		{
			if (_disposed)
			{
				return;
			}

			if (disposing)
			{
				// Cleanup managed
			}

			// Cleanup unmanaged
			StopPerformanceCounterLogs();
			DeletePerformanceCounterCollections();

			_disposed = true;
		}

		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		~PerformanceCounterLog()
		{
			Dispose(false);
		}
		#endregion

		private void CreatePerformanceCounterCollections()
		{
			string commandline;
			foreach (PerformanceCounterLogInfo info in this.Infos)
			{
				if (info.Username == null)
				{
					commandline = string.Format(@"create counter {0} -si {1} -cf {2} -o {3} -f csv",
						info.Name,
						info.LogIntervalInSeconds,
						info.PerformanceCounterFilename,
						info.OutputFilename);
					CallLogman(commandline);
				}
				else
				{
					commandline = string.Format(@"-s \\{0} -u {6} -p {7} {1} create counter {2} -s {0} -si {3} -cf {4} -o {5} -f csv",
						info.MachineName,
						info.LogManExePath,
						info.Name,
						info.LogIntervalInSeconds,
						info.PerformanceCounterFilename,
						info.OutputFilename,
						info.Username,
						info.Password);
					CallPsExec(commandline);
				}
			}
		}

		private void DeletePerformanceCounterCollections()
		{
			string commandline;
			foreach (PerformanceCounterLogInfo info in Infos)
			{
				if (info.Username == null)
				{
					commandline = string.Format(@"delete {0}",
						info.Name);
					CallLogman(commandline);
				}
				else
				{
					commandline = string.Format(@"-s \\{0} -u {3} -p {4} {1} delete {2} -s {0}",
						info.MachineName,
						info.LogManExePath,
						info.Name,
						info.Username,
						info.Password);
					CallPsExec(commandline);
				}
			}
		}

		private void StartPerformanceCounterLogs()
		{
			string commandline;
			foreach (PerformanceCounterLogInfo info in Infos)
			{
				if (info.Username == null)
				{
					commandline = string.Format(@"start {0}",
						info.Name);
					CallLogman(commandline);
				}
				else
				{
					commandline = string.Format(@"-s \\{0} -u {3} -p {4} {1} start {2} -s {0}",
						info.MachineName,
						info.LogManExePath,
						info.Name,
						info.Username,
						info.Password);
					CallPsExec(commandline);
				}
			}
		}

		private void StopPerformanceCounterLogs()
		{
			string commandline;
			foreach (PerformanceCounterLogInfo info in Infos)
			{
				if (info.Username == null)
				{
					commandline = string.Format(@"stop {0}",
						info.Name);
					CallLogman(commandline);
				}
				else
				{
					commandline = string.Format(@"-s \\{0} -u {3} -p {4} {1} stop {2} -s {0}",
						info.MachineName,
						info.LogManExePath,
						info.Name,
						info.Username,
						info.Password);
					CallPsExec(commandline);
				}
			}
		}

		private void CallPsExec(string commandline)
		{
            WcfProcessHelper.StartChildProcessAndWaitForExit(PsExecExePath, commandline);
        }

		private void CallLogman(string commandline)
		{
            WcfProcessHelper.StartChildProcessAndWaitForExit(LogManExePath, commandline);
        }
	}
}
